﻿using System;
using System.Linq;
using NCP.Infrastructure.Common.Specification;
using NCP.Recruiting.ApplicationServices.Interfaces;
using NCP.Recruiting.ApplicationServices.Messaging.Resumes;
using NCP.Recruiting.ApplicationServices.ModelConversions;
using NCP.Recruiting.ApplicationServices.ViewModels;
using NCP.Recruiting.Domain.Aggregates.Resumes;
using NCP.Infrastructure.Common.Domain;
using NCP.Infrastructure.Common;
using Newtonsoft.Json;
using NCP.Recruiting.ApplicationServices.Contracts;
using NCP.Recruiting.Domain.Aggregates.Companies;
using NCP.Recruiting.Domain.Aggregates.Candidates;
using NCP.Recruiting.Domain.Shared;
using NCP.Recruiting.Domain.Aggregates.Bookmarks;

namespace NCP.Recruiting.ApplicationServices.Implementations
{
    public class ResumeAppService : IResumeAppService
    {
        private readonly IResumeRepository _resumeRepository;
        private readonly ISavedSearchRepository _savedSearchRepository;
        private readonly ICompanyRepository _companyRepository;
        private readonly ICandidateRepository _candidateRepository;
        private readonly IBookmarkRepository _bookmarkRepository;

        private const String _dateFormat = "yyyy/MM/dd";
        private const String _dateFormatTime = "yyyy/MM/dd HH:mm:ss";

        public ResumeAppService(IResumeRepository resumeRepository, ISavedSearchRepository savedSearchRepository, ICompanyRepository companyRepository, ICandidateRepository candidateRepository, IBookmarkRepository bookmarkRepository)
        {
            _resumeRepository = resumeRepository;
            _savedSearchRepository = savedSearchRepository;
            _companyRepository = companyRepository;
            _candidateRepository = candidateRepository;
            _bookmarkRepository = bookmarkRepository;
        }

        public ResumeViewModel GetViewModelById(Guid id)
        {
            var currentItem = _resumeRepository.Get(id);
            return currentItem.ConvertToViewModel();
        }

        #region 根据条件进行人才检索
        /// <summary>
        /// 根据条件进行人才检索
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public SearchResponse Search(SearchRequest request)
        {
            var response = new SearchResponse();
            try
            {
                Specification<Resume> specification = null;
                specification = ResumeSpecifications.GetByAgeRange(request.ResumeCondtion.MinAge, request.ResumeCondtion.MaxAge) &&
                    ResumeSpecifications.GetByDesiredIndustry(request.ResumeCondtion.DesiredIndustry) &&
                    ResumeSpecifications.GetByEducationLevel(request.ResumeCondtion.EducationLevel) &&
                    ResumeSpecifications.GetByJobTypeList(request.ResumeCondtion.JobTypeList) &&
                    ResumeSpecifications.GetByLastUpdate(request.ResumeCondtion.DayRange) &&
                    ResumeSpecifications.GetByMajor(request.ResumeCondtion.Major) &&
                    ResumeSpecifications.GetByReferenceNumber(request.ResumeCondtion.ReferenceNumber) &&
                    ResumeSpecifications.GetByWorkDescription(request.ResumeCondtion.Description) &&
                    ResumeSpecifications.GetByYearsOfExperience(request.ResumeCondtion.YearsOfExperience);

                var list = _resumeRepository.GetPagedList(request.PageIndex, request.PageSize, specification, x => x.LastUpdated);

                var resumeIdList = list.Select(x => x.Id);
                var bookmarkList = _bookmarkRepository.GetFiltered(x => resumeIdList.Contains(x.ResumeId) && x.CompanyId.Equals(request.CompanyId));

                var emptyLabel = "未知";
                var listItemModelList = list.Select(x => new ResumeListItemModel()
                {
                    Age = !x.BirthDate.HasValue ? emptyLabel : (DateTime.Now.Year - x.BirthDate.Value.Year - ((DateTime.Now.Month * 100 + DateTime.Now.Day) < (x.BirthDate.Value.Month * 100 + x.BirthDate.Value.Day) ? 1 : 0)).ToString(),
                    CurrentJob = x.CurrentJob,
                    DesiredIndustry = !x.DesiredIndustry.HasValue ? emptyLabel : LovHandler.GetNameByLovValue(x.DesiredIndustry.Value),
                    EducationLevel = !x.EducationLevel.HasValue ? emptyLabel : LovHandler.GetNameByLovValue(x.EducationLevel.Value),
                    Gender = x.Gender,
                    Id = x.Id,
                    LastUpdate = x.LastUpdated.ToString(_dateFormat),
                    Major = !x.Major.HasValue ? emptyLabel : LovHandler.GetNameByLovValue(x.Major.Value),
                    Name = x.FullName,
                    Telephone = x.Tel,
                    YearsOfExperience = !x.YearsOfExperience.HasValue ? emptyLabel : LovHandler.GetNameByLovValue(x.YearsOfExperience.Value),
                    IsBookmarked = bookmarkList.Any(b => b.ResumeId.Equals(x.Id))
                });

                response.ListItemModelList = new PagedList<ResumeListItemModel>(listItemModelList, list.PageIndex, list.PageSize, list.TotalCount);
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion

        #region 获取搜索条件
        /// <summary>
        /// 获取搜索条件
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public GetConditionBySavedSearchIdResponse GetConditionBySavedSearchId(GetConditionBySavedSearchIdRequest request)
        {
            var response = new GetConditionBySavedSearchIdResponse();
            try
            {
                var savedSearch = _savedSearchRepository.Get(request.Id);
                response.SearchName = savedSearch.SearchName;
                //将查询条件进行反序列化
                response.ResumeCondtion = JsonConvert.DeserializeObject<ResumeCondtionViewModel>(savedSearch.Specifications);
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion

        #region 创建搜索器
        /// <summary>
        /// 创建搜索器
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public CreateSavedSearchResponse CreateSavedSearch(CreateSavedSearchRequest request)
        {
            var response = new CreateSavedSearchResponse();
            try
            {
                var company = _companyRepository.Get(request.CompanyId);
                var email = company.Email;
                var condition = request.ResumeCondtion.CopyItem<IResumeCondtionCommand, ResumeCondtionViewModel>();
                //将查询条件进行序列化
                var specifications = JsonConvert.SerializeObject(condition);
                var savedSearch = new SavedSearch()
                {
                    CompanyId = request.CompanyId,
                    DateCreated = DateTime.Now,
                    IsSubscribed = false,
                    LastUpdated = DateTime.Now,
                    SearchName = request.SearchName,
                    Specifications = specifications,
                    Email = email
                };
                savedSearch.GenerateNewIdentity();
                _savedSearchRepository.Add(savedSearch);
                _savedSearchRepository.UnitOfWork.Commit();
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion

        #region 更新搜索器
        /// <summary>
        /// 更新搜索器
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public UpdateSavedSearchResponse UpdateSavedSearch(UpdateSavedSearchRequest request)
        {
            var response = new UpdateSavedSearchResponse();
            try
            {
                var savedSearch = _savedSearchRepository.Get(request.Id);
                var condition = request.ResumeCondtion.CopyItem<IResumeCondtionCommand, ResumeCondtionViewModel>();
                //将查询条件进行序列化
                savedSearch.Specifications = JsonConvert.SerializeObject(condition);
                savedSearch.LastUpdated = DateTime.Now;
                _savedSearchRepository.Modify(savedSearch);
                _savedSearchRepository.UnitOfWork.Commit();
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion

        #region 获取搜索器一览
        /// <summary>
        /// 获取搜索器一览
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public GetSavedSearchListResponse GetSavedSearchList(GetSavedSearchListRequest request)
        {
            var response = new GetSavedSearchListResponse();
            try
            {
                Specification<SavedSearch> specification = null;
                specification = SavedSearchSpecifications.GetByCompany(request.CompanyId);
                var list = _savedSearchRepository.GetPagedList(request.PageIndex, request.PageSize, specification, x => x.LastUpdated);
                var listItemModelList = list.Select(x => new SavedSearchListItemModel
                {
                    Id = x.Id,
                    Frequency = x.Frequency.HasValue ? x.Frequency.ToString() : String.Empty,
                    IsSubscribed = x.IsSubscribed,
                    SearchName = x.SearchName,
                    Talents = x.Talents.HasValue ? x.Talents.ToString() : String.Empty,
                    Email = x.Email,
                    LastSearched = x.LastSearched.HasValue ? x.LastSearched.Value.ToString(_dateFormatTime) : String.Empty
                });
                response.ListItemModelList = new PagedList<SavedSearchListItemModel>(listItemModelList, list.PageIndex, list.PageSize, list.TotalCount);
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion

        #region 删除搜索器
        public DeleteSavedSearchResponse DeleteSavedSearch(DeleteSavedSearchRequest request)
        {
            var response = new DeleteSavedSearchResponse();
            try
            {
                var entity = _savedSearchRepository.Get(request.Id);
                _savedSearchRepository.Remove(entity);
                _savedSearchRepository.UnitOfWork.Commit();
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion

        #region 退订
        public UnsubscribeResponse Unsubscribe(UnsubscribeRequest request)
        {
            var response = new UnsubscribeResponse();
            try
            {
                var entity = _savedSearchRepository.Get(request.Id);
                entity.IsSubscribed = false;
                entity.LastUpdated = DateTime.Now;
                entity.Talents = null;
                entity.Frequency = null;
                _savedSearchRepository.Modify(entity);
                _savedSearchRepository.UnitOfWork.Commit();
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion

        #region 订阅
        /// <summary>
        /// 订阅
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public SubscribeResponse Subscribe(SubscribeRequest request)
        {
            var response = new SubscribeResponse();
            try
            {
                var entity = _savedSearchRepository.Get(request.ResumeSubscribe.Id);
                entity.IsSubscribed = true;
                entity.LastUpdated = DateTime.Now;
                entity.Talents = request.ResumeSubscribe.Talents;
                entity.Frequency = request.ResumeSubscribe.Frequency;
                entity.Email = request.ResumeSubscribe.Email;
                _savedSearchRepository.Modify(entity);
                _savedSearchRepository.UnitOfWork.Commit();
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion

        #region 通过搜索器进行检索
        /// <summary>
        /// 通过搜索器进行检索
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public SearchBySearcherIdResponse SearchBySearcherId(SearchBySearcherIdRequest request)
        {
            var response = new SearchBySearcherIdResponse();
            try
            {
                //获取检索条件
                var resumeCondtion = GetConditionBySavedSearchId(new GetConditionBySavedSearchIdRequest()
                {
                    Id = request.SearcherId
                }).ResumeCondtion;
                //取出对应的人员
                var list = Search(new SearchRequest()
                {
                    PageIndex = request.PageIndex,
                    PageSize = request.PageSize,
                    ResumeCondtion = resumeCondtion,
                    CompanyId = request.CompanyId
                }).ListItemModelList;
                response.ListItemModelList = list;
                //更新搜索器使用时间
                var savedSearch = _savedSearchRepository.Get(request.SearcherId);
                savedSearch.LastSearched = DateTime.Now;
                _savedSearchRepository.Modify(savedSearch);
                _savedSearchRepository.UnitOfWork.Commit();
            }
            catch (Exception ex)
            {
                response.Exception = ex;
            }
            return response;
        }
        #endregion

        #region 获取简历信息
        /// <summary>
        /// 获取简历信息
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public GetResumeInfoResponse GetResumeInfo(GetResumeInfoRequest request)
        {
            var currentItem = _resumeRepository.Get(request.ResumeId);
            var model = currentItem.ConvertToViewModel();
            var specification = CandidateSpecifications.GetCandidatesByCompanyId(request.CompanyId) &&
                CandidateSpecifications.GetCandidatesByResumeId(request.ResumeId) &&
                CandidateSpecifications.GetCandidatesBySource(CandidateSourceType.Company);
            var candidate = _candidateRepository.GetFiltered(specification.SatisfiedBy()).FirstOrDefault();
            //是否显示联系信息
            model.IsShowContact = candidate != null;
            return new GetResumeInfoResponse() { ResumeViewModel = model };
        }
        #endregion
    }
}
